#!python3
#coding:utf-8
import os

cur_path = os.path.dirname(os.path.abspath(__file__))
root_path = os.path.join(cur_path, "../..")
root_path = os.path.abspath(root_path)


def __getProjs(rpath):
    for path, dirs, files in os.walk(rpath):
        for file in files:
            fpath, ext = os.path.splitext(file)
            if ext != '.vcxproj':
                continue
            proj_path = os.path.join(path, file)
            yield proj_path

def GetAndTransProjPathAndData_FromVS2010_TO_VS2013(rpath):
    need_update = dict()
    for proj_path in __getProjs(rpath):
        from xml.etree import ElementTree
        def_ns = 'http://schemas.microsoft.com/developer/msbuild/2003'
        def_ns_str = r'{{{}}}'.format(def_ns)
        ElementTree.register_namespace('', def_ns)

        et = ElementTree.parse(proj_path)
        proj_node = et.getroot()
        if proj_node is None or proj_node.tag != def_ns_str+'Project':
            continue
        toolsVersion = proj_node.attrib.get('ToolsVersion', None)
        if toolsVersion != '4.0':
            continue
        projGroups = proj_node.findall(def_ns_str+'PropertyGroup')
        if projGroups is None or len(projGroups) == 0:
            continue
        is_need_upgrade = False
        for nd in projGroups:
            labNode = nd.attrib.get('Label', None)
            if labNode is None or labNode != 'Configuration':
                continue
            new_node = nd.makeelement(def_ns_str+'PlatformToolset', {})
            new_node.text = 'v120'
            is_need_upgrade = True
            nd.append(new_node)
        if is_need_upgrade:
            proj_node.attrib['ToolsVersion'] = '12.0'
            need_update[proj_path] = et
    return need_update

def GetAndTransProjPathAndData_FromVS2013_TO_VS2010(rpath):
    need_update = dict()
    for proj_path in __getProjs(rpath):
        from xml.etree import ElementTree
        def_ns = 'http://schemas.microsoft.com/developer/msbuild/2003'
        def_ns_str = r'{{{}}}'.format(def_ns)
        ElementTree.register_namespace('', def_ns)
        et = ElementTree.parse(proj_path)
        proj_node = et.getroot()
        if proj_node is None or proj_node.tag != def_ns_str+'Project':
            continue
        toolsVersion = proj_node.attrib.get('ToolsVersion', None)
        if toolsVersion != '12.0':
            continue
        projGroups = proj_node.findall(def_ns_str+'PropertyGroup')
        if projGroups is None or len(projGroups) == 0:
            continue
        is_need_upgrade = False
        for nd in projGroups:
            labNode = nd.attrib.get('Label', None)
            if labNode is None or labNode != 'Configuration':
                continue
            for need_rm in nd.findall(def_ns_str+'PlatformToolset'):
                nd.remove(need_rm)
                is_need_upgrade = True
        if is_need_upgrade:
            proj_node.attrib['ToolsVersion'] = '4.0'
            need_update[proj_path] = et
    return need_update


def TransSLN(slnPath, vstr, vsVer):
    import codecs

    with open(slnPath, "rt", encoding="utf-16") as slnFile:
        slnLists = list(slnFile)
    #vs 2013 : 'Microsoft Visual Studio Solution File, Format Version 12.00'
    #vs 2010 : 'Microsoft Visual Studio Solution File, Format Version 11.00'
    import re
    rFmtVer = re.compile(r'Microsoft Visual Studio Solution File, Format Version\s*([0-9]+\.[0-9]+)')
    rFmtVSVer = re.compile(r'# Visual Studio ([0-9])')
    is_need_save = False
    for i in range(len(slnLists)):
        if rFmtVer is None and rFmtVSVer is None:
            break

        if rFmtVer:
            m = rFmtVer.search(slnLists[i])
            if m:
                rFmtVer = None
                fileVer = m.group(1)
                if fileVer != vstr:
                    slnLists[i] = 'Microsoft Visual Studio Solution File, Format Version {}\n'.format(vstr)
                    is_need_save = True
                    continue
        if rFmtVSVer:
            m = rFmtVSVer.search(slnLists[i])
            if m:
                rFmtVSVer = None
                fileVer = m.group(1)
                if fileVer != vsVer:
                    slnLists[i] = '# Visual Studio {}\n'.format(vsVer)
                    is_need_save = True
                    continue

    if is_need_save:
        with open(slnPath, "wt", encoding="utf-16") as slnFile:
            slnFile.write(''.join(slnLists))

    #import os.path
    doc_path = os.path.dirname(slnPath)
    doc_root_path = os.path.join(doc_path, "..")
    doc_root_path = os.path.abspath(doc_root_path)
    if vstr == '12.00':
        projs = GetAndTransProjPathAndData_FromVS2010_TO_VS2013(doc_root_path)
    elif vstr == '11.00':
        projs = GetAndTransProjPathAndData_FromVS2013_TO_VS2010(doc_root_path)
    #Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lolix", "..\root_include\build\compont\lolix\lolix.vcxproj", "{B29F4D1E-5A40-4BEA-A594-ED65FB76220F}"
    rFmtProject = re.compile(r'Project\(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\"\)\s*=\s*\"[^\"].*\", \"([^\"]+)\",')
    for x in range(len(slnLists)):
        proj_path_match = rFmtProject.search(slnLists[x])
        if proj_path_match is None:
            continue
        proj_path = proj_path_match.group(1)
        proj_path = os.path.abspath(os.path.join(doc_path, proj_path))
        et = projs.get(proj_path, None)
        if et is None:
            continue
        et.write(proj_path, xml_declaration=True, encoding='utf-8')
        print('Trans:' + proj_path)


if __name__ == "__main__":
    import sys
    slnPath = os.path.join(root_path, "work_space/work_space.sln")
    if len(sys.argv) > 1:
        slnPath = os.path.join(root_path, sys.argv[1])

    print('1. trans vs2010 projects to vs2013 projects')
    print('2. trans vs2013 projects to vs2010 projects')
    type = input("input your choice:")
    if type == '1':
        TransSLN(slnPath, '12.00', '2013')
    elif type == '2':
        TransSLN(slnPath, '11.00', '2010')
